﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lidgren.Network;
using Microsoft.Xna.Framework;

namespace MvdDonk.Bomberman.Lib
{

    public class PlayerShit
    {
        public PlayerShit(long networkId)
        {
            NetworkId = networkId;
        }

        public long NetworkId { get; set; }
        public EntityMovementState MovementState { get; set; }
        public Vector2 MovementVector { get; set; }
        public Vector2 Position { get; set; }
    }

    public class Server
    {
        private List<PlayerShit> PlayerInfo = new List<PlayerShit>();

        private NetServer server;
        private double nextSendUpdates;
        private double nextSendUpdates2;

        public Server(string serverName, int serverPort)
        {
            nextSendUpdates = NetTime.Now;
            nextSendUpdates2 = NetTime.Now;

            Console.WriteLine("Initializing server");
            //Create server
            var config = new NetPeerConfiguration(serverName);
            config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            config.Port = serverPort;

            server = new NetServer(config);
            Console.WriteLine("Starting server...");
            server.Start();
            Console.WriteLine("Server started on port: " + serverPort);
        }

        public void Poll()
        {
            NetIncomingMessage msg;
            while ((msg = server.ReadMessage()) != null)
            {
                switch (msg.MessageType)
                {
                    case NetIncomingMessageType.DiscoveryRequest:
                        Console.WriteLine("Server received a discovery request from a client; send a discovery response (with no extra data attached)");
                        server.SendDiscoveryResponse(null, msg.SenderEndpoint);
                        break;
                    case NetIncomingMessageType.VerboseDebugMessage:
                    case NetIncomingMessageType.DebugMessage:
                    case NetIncomingMessageType.WarningMessage:
                    case NetIncomingMessageType.ErrorMessage:
                        //
                        // Just print diagnostic messages to console
                        //
                        Console.WriteLine(msg.ReadString());
                        break;
                    case NetIncomingMessageType.StatusChanged:
                        NetConnectionStatus status = (NetConnectionStatus)msg.ReadByte();
                        if (status == NetConnectionStatus.Connected)
                        {
                            //
                            // A new player just connected!
                            //
                            Console.WriteLine(NetUtility.ToHexString(msg.SenderConnection.RemoteUniqueIdentifier) + " connected!");

                            PlayerInfo.Add(new PlayerShit(msg.SenderConnection.RemoteUniqueIdentifier));
                        }

                        break;
                    case NetIncomingMessageType.Data:
                        //
                        // The client sent input to the server
                        //

                        //char action = (char)msg.ReadBytes(2)[0];
                        //switch (action)
                        //{
                        //    case 'P':
                        //        //short xinput = msg.ReadInt16();
                        //        //short yinput = msg.ReadInt16();
                        //        //Console.WriteLine(string.Format("Received position update: [{0}, {1}]", xinput, yinput));
                        //        //short[] pos = msg.SenderConnection.Tag as short[];

                        //        //// fancy movement logic goes here; we just append input to position
                        //        //pos[0] = xinput;
                        //        //pos[1] = yinput;
                        //        break;
                        //    case 'M':
                        var receivedMsg = MessageFinder.GetMessageFromClient(msg);
                        if (receivedMsg is MovementMessage)
                        {
                            var typed = receivedMsg as MovementMessage;
                            var player = PlayerInfo.FirstOrDefault(p => p.NetworkId == receivedMsg.NetworkId);
                            player.MovementState = typed.MovementState;
                            player.MovementVector = typed.MovementVector;
                            Console.WriteLine(string.Format("Received movement update: [{0}, {1}]", typed.MovementVector.X, typed.MovementVector.Y));
                        }
                        if (receivedMsg is PositionMessage)
                        {
                            var typed = receivedMsg as PositionMessage;
                            var player = PlayerInfo.FirstOrDefault(p => p.NetworkId == receivedMsg.NetworkId);
                            player.Position= typed.Position;
                            Console.WriteLine(string.Format("Received position update: [{0}, {1}]", typed.Position.X, typed.Position.Y));
                        }
                        break;
                    //}

                    //break;
                }


                //
                // send position updates 30 times per second
                //
                double now = NetTime.Now;
                if (now > nextSendUpdates)
                {
                    // Yes, it's time to send position updates

                    Console.WriteLine("Sending data to clients");
                    // for each player...
                    foreach (NetConnection player in server.Connections)
                    {
                        foreach (var otherPlayer in PlayerInfo)
                        {
                            var om = new MovementMessage(otherPlayer.MovementVector, otherPlayer.MovementState, otherPlayer.NetworkId);
                            om.SendToClient(server, player);
                        }
                    }

                    // schedule next update
                    nextSendUpdates += (1.0 / 30.0);
                }


                //
                // send position updates 30 times per second
                //
                if (now > nextSendUpdates2)
                {
                    // Yes, it's time to send position updates

                    Console.WriteLine("Sending data to clients");
                    // for each player...
                    foreach (NetConnection player in server.Connections)
                    {
                        foreach (var otherPlayer in PlayerInfo)
                        {
                            var om = new PositionMessage(otherPlayer.Position, otherPlayer.NetworkId);
                            om.SendToClient(server, player);
                        }
                    }

                    // schedule next update
                    nextSendUpdates2 += (1.0 / 10.0);
                }
            }
        }
    }
}
